package com.bubbo.rpc.client.service;

import com.bubbo.rpc.client.bean.RpcRequest;
import com.bubbo.rpc.client.bean.RpcResponse;
import com.bubbo.rpc.client.util.StringUtil;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * Created by waasdasd on 2017/3/29.
 */
public class BubboServiceHandler extends SimpleChannelInboundHandler<RpcRequest> {

    private static final Logger LOGGER = LoggerFactory.getLogger(BubboServiceHandler.class);


    private final Map<String, Object> handlerMap;

    public BubboServiceHandler(Map<String, Object> handlerMap) {
        this.handlerMap = handlerMap;
    }

    @Override
    public void channelRead0(final ChannelHandlerContext ctx, RpcRequest reqeust) throws Exception {
        RpcResponse response = new RpcResponse();
        response.setRequestId(reqeust.getRequestId());
        try {
            Object result = handler(reqeust);
            response.setResult(result);
        } catch (Exception e) {
            LOGGER.error("handler erro");
            e.printStackTrace();
        }
        //RPC响应
        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
    }

    private Object handler(RpcRequest request) throws Exception {
        String serviceName = request.getInterfaceName();
        String serviceVersion = request.getServiceVersion();
        if (StringUtil.isNotEmpty(serviceVersion)) {
            serviceVersion += serviceVersion;
        }
        Object serviceBean = handlerMap.get(serviceName);
        if (serviceBean == null) {
            throw new RuntimeException(String.format("can not find service bean by key: %s", serviceName));
        }
        Class<?> serviceClass = serviceBean.getClass();
        String methodName = request.getMethodName();
        Class<?>[] paramterType = request.getParamterType();
        Object[] parameters = request.getParameters();
        Method method = serviceClass.getMethod(methodName, paramterType);
        method.setAccessible(true);
        return method.invoke(serviceBean, parameters);
    }
}
